<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Anki卡片转换工具</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .container {
            background: white;
            border-radius: 10px;
            padding: 30px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        h1 {
            color: #2c3e50;
            text-align: center;
            margin-bottom: 30px;
        }
        .section {
            margin-bottom: 30px;
        }
        .section h2 {
            color: #34495e;
            border-bottom: 2px solid #3498db;
            padding-bottom: 5px;
        }
        textarea {
            width: 100%;
            min-height: 200px;
            border: 1px solid #ddd;
            border-radius: 5px;
            padding: 10px;
            font-family: 'Consolas', 'Monaco', monospace;
            font-size: 14px;
            resize: vertical;
        }
        .button-group {
            text-align: center;
            margin: 20px 0;
        }
        button {
            background: #3498db;
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
            margin: 0 10px;
            transition: background 0.3s;
        }
        button:hover {
            background: #2980b9;
        }
        button.secondary {
            background: #95a5a6;
        }
        button.secondary:hover {
            background: #7f8c8d;
        }
        .result {
            background: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 5px;
            padding: 15px;
            margin-top: 20px;
        }
        .instructions {
            background: #e8f4fd;
            border-left: 4px solid #3498db;
            padding: 15px;
            margin: 20px 0;
            border-radius: 5px;
        }
        .file-input {
            margin: 15px 0;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        input[type="file"] {
            display: none;
        }
        .file-input label {
            background: #f8f9fa;
            color: #495057;
            border: 1px solid #ced4da;
            padding: 8px 16px;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s;
        }
        .file-input label:hover {
            background: #e9ecef;
            border-color: #adb5bd;
        }
        .file-input span {
            font-size: 13px;
            color: #6c757d;
        }
        .tabs {
            display: flex;
            margin-bottom: 20px;
            border-bottom: 1px solid #ddd;
        }
        .tab {
            padding: 10px 20px;
            cursor: pointer;
            border: 1px solid transparent;
            border-bottom: none;
            border-radius: 5px 5px 0 0;
            margin-right: 5px;
        }
        .tab.active {
            background: white;
            border-color: #ddd;
            border-bottom-color: white;
            margin-bottom: -1px;
        }
        .tab-content {
            display: none;
        }
        .tab-content.active {
            display: block;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🎴 Anki卡片转换工具</h1>
        
        <div class="instructions">
            <strong>使用说明：</strong><br>
            1. 选择输入格式（自定义格式或简易格式）<br>
            2. 输入内容或上传TXT文件（点击"选择TXT文件"按钮或拖拽文件到文本框）<br>
            3. 点击转换按钮<br>
            4. 下载转换后的Anki导入文件
        </div>

        <div class="tabs">
            <div class="tab active" onclick="showTab('custom')">自定义格式</div>
            <div class="tab" onclick="showTab('simple')">简易格式</div>
            <div class="tab" onclick="showTab('anki')">Anki导入指南</div>
        </div>

        <div id="custom" class="tab-content active">
            <div class="section">
                <h2>自定义格式转换</h2>
                <p>支持以下格式：</p>
                <div class="file-input">
                    <input type="file" id="customFileInput" accept=".txt" onchange="handleFileUpload(event, 'customInput')">
                    <label for="customFileInput">选择TXT文件</label>
                    <span style="margin-left: 10px; color: #666;">或拖拽文件到下方文本框</span>
                </div>
                <textarea id="customInput" placeholder="在此粘贴自定义格式内容...
光纤通道(FC)为何更适合金融高频交易场景？
存储协议
---
✅ 微秒级延迟要求+零丢包保障
📚 光纤协议栈比TCP/IP精简，省略了重传和拥塞控制机制，直接映射到物理层
❗ FC像F1赛车（专用赛道/极简设计），IP像货车（通用公路/频繁检修）
⛔️ 曾将网络带宽视为低延迟首要因素，忽略了协议开销的影响
🔍 延迟敏感型系统需要绕过传统协议栈的冗余机制
===============
IP SAN和FC SAN的主要区别是什么？
存储协议
---
✅ 传输协议不同：FC使用光纤通道协议，IP SAN使用TCP/IP协议
📚 FC SAN专为存储设计，提供predictable性能；IP SAN基于现有IP网络，成本更低但性能有波动
❗ FC像专用高速公路，IP SAN像普通公路共享车流
⛔️ 曾认为两者只是速度差异，忽略了协议可靠性的根本区别
🔍 选择取决于对性能可预测性和成本的不同权衡
==============="></textarea>
                <div class="button-group">
                    <button onclick="loadSample('custom')">加载示例</button>
                    <button onclick="convertCustom()">转换格式</button>
                    <button onclick="downloadResult()" id="downloadBtn" style="display:none;">下载文件</button>
                </div>
            </div>
        </div>

        <div id="simple" class="tab-content">
            <div class="section">
                <h2>简易格式转换</h2>
                <p>每行格式：问题\t答案</p>
                <div class="file-input">
                    <input type="file" id="simpleFileInput" accept=".txt" onchange="handleFileUpload(event, 'simpleInput')">
                    <label for="simpleFileInput">选择TXT文件</label>
                    <span style="margin-left: 10px; color: #666;">或拖拽文件到下方文本框</span>
                </div>
                <textarea id="simpleInput" placeholder="在此粘贴简易格式内容...
什么是RESTful API？	RESTful API是一种基于REST架构风格的网络应用程序接口
什么是SQL注入？	SQL注入是通过在输入字段中插入恶意SQL代码来攻击数据库的技术
什么是负载均衡？	负载均衡是将网络流量分配到多个服务器的技术"></textarea>
                <div class="button-group">
                    <button onclick="loadSample('simple')">加载示例</button>
                    <button onclick="convertSimple()">转换格式</button>
                    <button onclick="downloadResult()" id="downloadBtn2" style="display:none;">下载文件</button>
                </div>
            </div>
        </div>

        <div id="anki" class="tab-content">
            <div class="section">
                <h2>Anki导入步骤</h2>
                <div class="instructions">
                    <ol>
                        <li><strong>打开Anki</strong> - 启动Anki应用程序</li>
                        <li><strong>选择牌组</strong> - 选择要导入卡片的牌组</li>
                        <li><strong>导入文件</strong> - 点击 文件 → 导入</li>
                        <li><strong>选择文件</strong> - 选择转换生成的.txt文件</li>
                        <li><strong>设置导入选项</strong>:
                            <ul>
                                <li>类型：选择"基础"或"基础（和反向卡片）"</li>
                                <li>牌组：选择目标牌组</li>
                                <li>字段分隔符：选择"制表符"</li>
                            </ul>
                        </li>
                        <li><strong>字段映射</strong> - 确保字段正确映射</li>
                        <li><strong>开始导入</strong> - 点击"导入"按钮</li>
                    </ol>
                </div>
            </div>
        </div>

        <div class="result" id="result" style="display:none;">
            <h3>转换结果</h3>
            <textarea id="resultText" readonly></textarea>
        </div>
    </div>

    <script>
        let currentResult = '';

        // 设置页面编码
        document.charset = 'UTF-8';

        function showTab(tabName) {
            // 隐藏所有tab内容
            document.querySelectorAll('.tab-content').forEach(tab => {
                tab.classList.remove('active');
            });
            document.querySelectorAll('.tab').forEach(tab => {
                tab.classList.remove('active');
            });
            
            // 显示选中的tab
            document.getElementById(tabName).classList.add('active');
            event.target.classList.add('active');
        }

        function loadSample(type) {
            if (type === 'custom') {
                document.getElementById('customInput').value = `光纤通道(FC)为何更适合金融高频交易场景？
存储协议
---
✅ 微秒级延迟要求+零丢包保障
📚 光纤协议栈比TCP/IP精简，省略了重传和拥塞控制机制，直接映射到物理层
❗ FC像F1赛车（专用赛道/极简设计），IP像货车（通用公路/频繁检修）
⛔️ 曾将网络带宽视为低延迟首要因素，忽略了协议开销的影响
🔍 延迟敏感型系统需要绕过传统协议栈的冗余机制
===============
IP SAN和FC SAN的主要区别是什么？
存储协议
---
✅ 传输协议不同：FC使用光纤通道协议，IP SAN使用TCP/IP协议
📚 FC SAN专为存储设计，提供predictable性能；IP SAN基于现有IP网络，成本更低但性能有波动
❗ FC像专用高速公路，IP SAN像普通公路共享车流
⛔️ 曾认为两者只是速度差异，忽略了协议可靠性的根本区别
🔍 选择取决于对性能可预测性和成本的不同权衡
===============`;
            } else {
                document.getElementById('simpleInput').value = `什么是RESTful API？	RESTful API是一种基于REST架构风格的网络应用程序接口，使用HTTP方法对资源进行操作
什么是SQL注入？	SQL注入是通过在输入字段中插入恶意SQL代码来攻击数据库的技术
什么是负载均衡？	负载均衡是将网络流量分配到多个服务器的技术，以提高性能和可靠性
什么是微服务架构？	微服务架构是将单一应用程序划分为一组小的、独立的服务的方法
什么是容器化？	容器化是将应用程序及其依赖打包成轻量级、可移植的容器的技术`;
            }
        }

        function parseCustomFormat(content) {
            const cards = [];
            const cardBlocks = content.split('===============');
            
            // 创建emoji正则表达式，仅删除指定的emoji表情符号
            const emojiRegex = /[✅📚❗⛔️🔍]/g;
            
            function removeEmoji(text) {
                // 仅移除行首的指定emoji符号
                return text.replace(/^[✅📚❗⛔️🔍]\s*/, '').trim();
            }
            
            for (const block of cardBlocks) {
                const trimmed = block.trim();
                if (!trimmed || !trimmed.includes('---')) continue;
                
                const [front, back] = trimmed.split('---');
                const frontLines = front.trim().split('\n').map(l => l.trim()).filter(l => l);
                const backLines = back.trim().split('\n').map(l => l.trim());
                
                if (frontLines.length === 0) continue;
                
                const card = {
                    question: removeEmoji(frontLines[0] || ''),
                    category: removeEmoji(frontLines[1] || '未分类'),
                    core_answer: '',
                    full_explanation: '',
                    memory_tip: '',
                    common_mistake: '',
                    essential_understanding: ''
                };
                
                // 支持多行文本累积
                let currentField = null;
                let currentContent = [];
                
                for (const line of backLines) {
                    const trimmedLine = line.trim();
                    if (!trimmedLine) continue;
                    
                    // 检查是否是新字段标记
                    if (trimmedLine.startsWith('✅')) {
                        // 保存前一个字段的内容
                        if (currentField && currentContent.length > 0) {
                            card[currentField] = removeEmoji(currentContent.join('<br>').trim());
                        }
                        currentField = 'core_answer';
                        currentContent = [removeEmoji(trimmedLine.substring(1).trim())];
                    } else if (trimmedLine.startsWith('📚')) {
                        if (currentField && currentContent.length > 0) {
                            card[currentField] = removeEmoji(currentContent.join('<br>').trim());
                        }
                        currentField = 'full_explanation';
                        currentContent = [removeEmoji(trimmedLine.substring(1).trim())];
                    } else if (trimmedLine.startsWith('❗')) {
                        if (currentField && currentContent.length > 0) {
                            card[currentField] = removeEmoji(currentContent.join('<br>').trim());
                        }
                        currentField = 'memory_tip';
                        currentContent = [removeEmoji(trimmedLine.substring(1).trim())];
                    } else if (trimmedLine.startsWith('⛔️')) {
                        if (currentField && currentContent.length > 0) {
                            card[currentField] = removeEmoji(currentContent.join('<br>').trim());
                        }
                        currentField = 'common_mistake';
                        currentContent = [removeEmoji(trimmedLine.substring(1).trim())];
                    } else if (trimmedLine.startsWith('🔍')) {
                        if (currentField && currentContent.length > 0) {
                            card[currentField] = removeEmoji(currentContent.join('<br>').trim());
                        }
                        currentField = 'essential_understanding';
                        currentContent = [removeEmoji(trimmedLine.substring(1).trim())];
                    } else {
                        // 累积多行内容
                        if (currentField && trimmedLine) {
                            currentContent.push(removeEmoji(trimmedLine));
                        }
                    }
                }
                
                // 保存最后一个字段的内容
                if (currentField && currentContent.length > 0) {
                    card[currentField] = removeEmoji(currentContent.join('<br>').trim());
                }
                
                cards.push(card);
            }
            
            return cards;
        }

        function parseSimpleFormat(content) {
            const cards = [];
            const lines = content.split('\n').map(l => l.trim()).filter(l => l);
            
            for (const line of lines) {
                if (line.includes('\t')) {
                    const [question, answer] = line.split('\t');
                    cards.push({
                        question: question.trim(),
                        category: '未分类',
                        core_answer: answer.trim(),
                        full_explanation: '',
                        memory_tip: '',
                        common_mistake: '',
                        essential_understanding: ''
                    });
                }
            }
            
            return cards;
        }

        function formatForAnki(cards) {
            const lines = ['问题\t知识点分类\t核心答案\t完整解析\t记忆技巧\t我的误区\t本质理解'];
            
            for (const card of cards) {
                const escape = (str) => str.replace(/\t/g, ' ');
                const line = [
                    escape(card.question),
                    escape(card.category),
                    escape(card.core_answer),
                    escape(card.full_explanation),
                    escape(card.memory_tip),
                    escape(card.common_mistake),
                    escape(card.essential_understanding)
                ].join('\t');
                lines.push(line);
            }
            
            return lines.join('\n');
        }

        function convertCustom() {
            const input = document.getElementById('customInput').value;
            if (!input.trim()) {
                alert('请输入内容');
                return;
            }
            
            const cards = parseCustomFormat(input);
            currentResult = formatForAnki(cards);
            
            document.getElementById('resultText').value = currentResult;
            document.getElementById('result').style.display = 'block';
            document.getElementById('downloadBtn').style.display = 'inline-block';
            
            alert(`成功转换 ${cards.length} 张卡片`);
        }

        function convertSimple() {
            const input = document.getElementById('simpleInput').value;
            if (!input.trim()) {
                alert('请输入内容');
                return;
            }
            
            const cards = parseSimpleFormat(input);
            currentResult = formatForAnki(cards);
            
            document.getElementById('resultText').value = currentResult;
            document.getElementById('result').style.display = 'block';
            document.getElementById('downloadBtn2').style.display = 'inline-block';
            
            alert(`成功转换 ${cards.length} 张卡片`);
        }

        function downloadResult() {
            if (!currentResult) {
                alert('请先转换内容');
                return;
            }
            
            // 使用UTF-8 BOM确保Excel等软件正确识别编码
            const BOM = '\uFEFF';
            const contentWithBOM = BOM + currentResult;
            
            const blob = new Blob([contentWithBOM], { 
                type: 'text/plain;charset=utf-8' 
            });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'anki_cards.txt';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        }

        // 文件上传支持
        function handleFileUpload(event, textareaId) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    document.getElementById(textareaId).value = e.target.result;
                };
                reader.readAsText(file);
            }
        }

        // 添加文件上传功能
        document.addEventListener('DOMContentLoaded', function() {
            const customInput = document.getElementById('customInput');
            const simpleInput = document.getElementById('simpleInput');
            
            function readFileWithEncoding(file, targetElement) {
                const reader = new FileReader();
                reader.onload = (e) => {
                    // 尝试检测和处理编码
                    let content = e.target.result;
                    targetElement.value = content;
                };
                
                // 尝试使用UTF-8编码读取
                reader.readAsText(file, 'UTF-8');
            }
            
            customInput.addEventListener('dragover', (e) => e.preventDefault());
            customInput.addEventListener('drop', (e) => {
                e.preventDefault();
                const file = e.dataTransfer.files[0];
                if (file) {
                    readFileWithEncoding(file, customInput);
                }
            });
            
            simpleInput.addEventListener('dragover', (e) => e.preventDefault());
            simpleInput.addEventListener('drop', (e) => {
                e.preventDefault();
                const file = e.dataTransfer.files[0];
                if (file) {
                    readFileWithEncoding(file, simpleInput);
                }
            });
        });
    </script>
</body>
</html>